package com.diorsunion.hedge.quota;

import com.diorsunion.hedge.dal.entity.stock.Stock;
import com.diorsunion.hedge.dal.entity.stock.StockPrice;
import com.diorsunion.hedge.domain.MACD;
import com.diorsunion.hedge.domain.Trend;
import com.google.common.collect.Sets;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Set;

/*************
 * MACD指标计算
 * MACD公式：
 * 12日EMA的计算：
 * EMA（12） = 前一日EMA（12） * 11/13 + 今日收盘价 * 2/13
 * 26日EMA的计算：
 * EMA（26） = 前一日EMA（26） * 25/27 + 今日收盘价 * 2/27
 * DIF = EMA（12） - EMA（26）
 * 今日DEA = （前一日DEA * 8/10 + 今日DIF * 2/10）
 * MACD = (dif-dea)*2
 * Created by harley-dog on 2016/5/3.
 */
public class MACDFilter implements StockPriceExFilter {

    int d1,d2;

    public MACDFilter(int d1, int d2) {
        this.d1 = d1;
        this.d2 = d2;
    }

    @Override
    public void filter(Stock stock,List<StockPrice> lastList,List<StockPrice> stockPriceList) {
        if (CollectionUtils.isEmpty(stockPriceList)) {
            return;
        }
        double ema12,ema26,dif,dea,macd;
        Trend macdTrend;
        StockPrice stockPrice0 = stockPriceList.get(0);
        //首先计算出stockPriceList[0]的MACD值，这个值可能要借助于lastList[last]的值
        //判断lastList[last].ex是否已经赋值可以通过ex.ema12,ema26,macdReversePrice的值，正常情况下这三个值不可能同时等于0
        if(CollectionUtils.isEmpty(lastList) ||
                (lastList.get(0).ex.ema12==0 && lastList.get(0).ex.ema26==0 &&  lastList.get(0).ex.macdReversePrice==0)){
            //如果lastList[last]为空，说明是库里的第一个stockPrice,则按初始值来计算
            ema12 = stockPriceList.get(0).close;
            ema26 = stockPriceList.get(0).close;
            dif = ema12 - ema26;
            dea = dif;
            macd = 0;
            macdTrend = Trend.E;
        }else{
            StockPrice stockPriceLast_last = lastList.get(lastList.size()-1);
            ema12 = stockPriceLast_last.ex.ema12 * (d1-1) / (d1+1) + 2d / (d1+1) * stockPrice0.close;
            ema26 = stockPriceLast_last.ex.ema26 * (d2-1) / (d2+1) + 2d / (d2+1) * stockPrice0.close;
            dif = ema12 - ema26;
            dea = stockPriceLast_last.ex.dea * 0.8d + dif * 0.2d;
            macd = 1.6d * dif - 1.6d * stockPriceLast_last.ex.dea;
            macdTrend = Trend.judge(stockPriceLast_last.ex.macd,macd);
        }
        double macdReversePrice = calcPriceByMacd(ema12,ema26,dea,macd);

        stockPrice0.ex.ema12 = ema12;
        stockPrice0.ex.ema26 = ema26;
        stockPrice0.ex.dif = dif;
        stockPrice0.ex.dea = dea;
        stockPrice0.ex.macd = macd;
        stockPrice0.ex.macdTrend = macdTrend;
        stockPrice0.ex.macdReversePrice = macdReversePrice;

        //stockPriceList[0]有了macd数据之后，stockPriceList[1-n]的就可以按照上一个的macd值来进行计算
        for (int i = 1; i < stockPriceList.size(); i++) {
            StockPrice stockPrice = stockPriceList.get(i);
            StockPrice stockPrice_yes = stockPriceList.get(i - 1);
            ema12 = stockPrice_yes.ex.ema12 * 11d / 13d + 2d / 13d * stockPrice.close;
            ema26 = stockPrice_yes.ex.ema26 * 25d / 27d + 2d / 27d * stockPrice.close;
            dif = ema12 - ema26;
            dea = stockPrice_yes.ex.dea * 0.8d + dif * 0.2d;
            macd = 1.6d * dif - 1.6d * stockPrice_yes.ex.dea;
            macdTrend = Trend.judge(stockPrice_yes.ex.macd,macd);
            double price = calcPriceByMacd(ema12,ema26,dea,macd);
            stockPrice.ex.ema12 = ema12;
            stockPrice.ex.ema26 = ema26;
            stockPrice.ex.dif = dif;
            stockPrice.ex.dea = dea;
            stockPrice.ex.macd = macd;
            stockPrice.ex.macdReversePrice = price;
            stockPrice.ex.macdTrend = macdTrend;
        }
    }

    private static final Set<MACD> getMACD(List<StockPrice> stockPriceList, int i) {
        Set<MACD> set = Sets.newHashSet();
        if (stockPriceList == null || stockPriceList.size() < 2) {
            return set;
        }
        StockPrice last = stockPriceList.get(i);
        StockPrice last_pre = stockPriceList.get(i - 1);
        if (last_pre.dif < last_pre.dea && last.dif > last.dea && last.dif < 0 && last.dea < 0) {
            set.add(new MACD(MACD.Type.JINCHA, 4));
        }
        if (last_pre.dif < last_pre.dea && last.dif > last.dea && last.dif > 0 && last.dea > 0 && last.macd > 0) {
            set.add(new MACD(MACD.Type.JINCHA, 3));
        }
        if (last_pre.dif < last_pre.dea && last.dif > last.dea && last.dif > 0 && last.dea > 0) {
            set.add(new MACD(MACD.Type.JINCHA, 2));
        }
        if (last_pre.dif < last_pre.dea && last.dif > last.dea) {
            set.add(new MACD(MACD.Type.JINCHA, 1));
        }
        if (last_pre.dif > last_pre.dea && last.dif < last.dea && last.dif > 0 && last.dea > 0) {
            set.add(new MACD(MACD.Type.SICHA, 4));
        }
        if (last_pre.dif > last_pre.dea && last.dif < last.dea && last.dif < 0 && last.dea < 0 && last.macd < 0) {
            set.add(new MACD(MACD.Type.SICHA, 3));
        }
        if (last_pre.dif > last_pre.dea && last.dif < last.dea && last.dif < 0 && last.dea < 0) {
            set.add(new MACD(MACD.Type.SICHA, 2));
        }
        if (last_pre.dif > last_pre.dea && last.dif < last.dea) {
            set.add(new MACD(MACD.Type.SICHA, 1));
        }
        if (stockPriceList.size() > 2 && i > 1) {
            StockPrice last_pre_pre = stockPriceList.get(i - 2);
            if (last_pre_pre.macd < last_pre.macd && last_pre.macd > last.macd) {
                set.add(new MACD(MACD.Type.top_divergence, 1));
            }
            if (last_pre_pre.macd < last_pre.macd && last_pre.macd > last.macd && last.macd > 0) {
                set.add(new MACD(MACD.Type.top_divergence, 2));
            }
            if (last_pre_pre.macd > last_pre.macd && last_pre.macd < last.macd) {
                set.add(new MACD(MACD.Type.buttom_divergence, 1));
            }
            if (last_pre_pre.macd > last_pre.macd && last_pre.macd < last.macd && last.macd < 0) {
                set.add(new MACD(MACD.Type.buttom_divergence, 2));
            }

        }
        return set;
    }

    //计算ema
    public static final double calcEma12(double s_ema12, double price){
        return s_ema12 * 11d / 13d + 2d / 13d * price;
    }

    //计算ema26
    public static final double calcEma26(double s_ema12, double close){
        return s_ema12 * 25d / 27d + 2d / 27d * close;
    }

    //计算dif
    public static final double calcDif(double s_ema12, double s_ema26, double price){
        double ema12 = calcEma12(s_ema12, price);
        double ema26 = calcEma26(s_ema26, price);
        return ema12 - ema26;
    }

    //计算dea
    public static final double calcDea(double s_ema12, double s_ema26, double s_dea, double price){
        double dif = calcDif(s_ema12, s_ema26, price);
        double dea = s_dea * 0.8d + dif * 0.2d;
        return dea;
    }

    //计算MACD
    public static final double calcMacdByPrice(double s_ema12,double s_ema26,double s_dea,double close){
        double dif = calcDif(s_ema12, s_ema26, close);
        double dea = calcDea(s_ema12, s_ema26, s_dea, close);
        double macd = (dif-dea)*2;
        return macd;
    }

    //利用MACD反推价格
    public static final double calcPriceByMacd(double s_ema12,double s_ema26,double s_dea,double macd){
        double price = (macd-1.6d*s_ema12*11d/13d+1.6d*s_ema26*25d/27d+1.6d*s_dea)/(1.6d * (2d/13d-2d/27d));
        return price;
    }
}
